# -*- coding: utf-8 -*-

from .models import Minion, Server, MinionDetail, ProcRunning
from .saltapi import salt
from django.utils import timezone
import urllib, urllib2, json
from saltops.settings import SERVER_LIST_ADDR

def traverseKey():
    params = {
        'client': 'wheel',
        'fun': 'key.list_all',
        'match': ''
    }
    result = salt.postRequest(params)
    result = result['return'][0]['data']['return']
    result.pop('local')
    print(result)

    ## 已接受key的节点状态并不能在此时确定
    for k in result['minions']:
        exists = Minion.objects.filter(key = k).exists()
        if exists:
            minion = Minion.objects.get(key = k)
            minion.type = 0
            minion.update_date = timezone.now()
            ## 其他的如主机状态, 创建时间等, 不是在此时确定的
            try:
                minion.save()
            except Exception as err:
                print(err)
        else:
            minion = {
                'key': k,
                'type': 0
            }
            try:
                Minion.objects.create(**minion)
            except Exception as err:
                print(err)
    ## 未接受, 已拒绝, 已禁止的节点状态都应为空    
    for k in result['minions_pre']:
        exists = Minion.objects.filter(key = k).exists()     
        if exists:
            minion = Minion.objects.get(key = k)
            minion.type = 1
            minion.update_date = timezone.now()
            try:
                minion.save()
            except Exception as err:
                print(err)
        else:
            minion = {
                'key': k,
                'type': 1, 
            }
            try:
                Minion.objects.create(**minion)
            except Exception as err:
                print(err)
    for k in result['minions_denied']:
        exists = Minion.objects.filter(key = k).exists()        
        if exists:
            minion = Minion.objects.get(key = k)
            minion.type = 2
            minion.update_date = timezone.now()
            try:
                minion.save()
            except Exception as err:
                print(err)
        else:
            minion = {
                'key': k,
                'type': 2, 
            }
            try:
                Minion.objects.create(**minion)
            except Exception as err:
                print(err)
    for k in result['minions_rejected']:
        exists = Minion.objects.filter(key = k).exists()        
        if exists:
            minion = Minion.objects.get(key = k)
            minion.type = 3
            minion.update_date = timezone.now()
            try:
                minion.save()
            except Exception as err:
                print(err)
        else:
            minion = {
                'key': k,
                'type': 3, 
            }
            try:
                Minion.objects.create(**minion)
            except Exception as err:
                print(err)
def healthCheck():
    '''
    Minion数据在健康检查的时候添加/更新, 但是没有能够显式删除的功能
    '''
    params = {
        'client': 'local',
        'fun': 'test.ping',
        'tgt': '*'
    }
    result = salt.postRequest(params)
    result = result['return'][0]
    for k in result.keys():
        exists = Minion.objects.filter(key = k).exists()
        if exists:
            minion = Minion.objects.get(key = k)
            minion.type = 0
            minion.status = result[k]
            minion.update_date = timezone.now()
            try:
                minion.save()
            except Exception as err:
                print(err)
        else:
            minion = {
                'key': k,
                'type': 0,
                'status': result[k],
                'create_date': timezone.now(),
                'update_date': timezone.now()
            }
            try:
                Minion.objects.create(**minion)
            except Exception as err:
                print(err)
    collectInfo()
    procDetect()

def collectInfo():
    '''
    收集minion节点必要的硬件信息
    ...目前只有硬件id
    '''
    params = {
        'client': 'local',
        'fun': 'grains.items',
        'tgt': '*'
    }
    result = salt.postRequest(params)
    result = result['return'][0]
    for i in result:
        if not result[i]:
            continue
        minion = Minion.objects.get(key = i)
        exists_detail = MinionDetail.objects.filter(minion = minion).exists()
        if exists_detail:
            detail = MinionDetail.objects.get(minion = minion)
            detail.hware_id     = result[i]['serialnumber']
            detail.kernel       = result[i]['kernelrelease']
            detail.cpu          = int(result[i]['num_cpus'])
            detail.memory       = int(result[i]['mem_total'])
            detail.os           = result[i]['os']
            detail.osrelease    = result[i]['osrelease']
            detail.saltpath     = result[i]['saltpath']
            detail.saltversion  = result[i]['saltversion']
            detail.pyversion    = '.'.join(result[i]['pythonversion'][:2])
            detail.osarch       = result[i]['osarch']
            detail.cpuarch      = result[i]['cpuarch']
            detail.cpu_model    = result[i]['cpu_model']
            detail.virtual      = result[i]['virtual']
            detail.mac          = result[i]['hwaddr_interfaces']
            detail.ipv4         = ','.join(result[i]['ipv4'])
            detail.disk         = ','.join(result[i]['disks'])
            try:
                detail.save()
            except Exception as err:
                print(err)
        else:
            detail = {
                'minion'        : minion,
                'hware_id'      : result[i]['serialnumber'],
                'kernel'        : result[i]['kernelrelease'],
                'cpu'           : int(result[i]['num_cpus']),
                'memory'        : int(result[i]['mem_total']),
                'os'            : result[i]['os'],
                'osrelease'     : result[i]['osrelease'],
                'saltpath'      : result[i]['saltpath'],
                'saltversion'   : result[i]['saltversion'],
                ## pythonversion字段为一个数值列表, [2, 7, 5, 'final'],
                ## 而join方法只能拼接字符串, 所以需要事先把每个成员转换成字符串
                'pyversion'     : '.'.join(map(str, result[i]['pythonversion'][:2])),
                'osarch'        : result[i]['osarch'],
                'cpuarch'       : result[i]['cpuarch'],
                'cpu_model'     : result[i]['cpu_model'],
                'virtual'       : result[i]['virtual'],
                'mac'           : result[i]['hwaddr_interfaces'],
                'ipv4'          : ','.join(result[i]['ipv4']),
                'disk'          : ','.join(result[i]['disks'])
            }
            try:            
                MinionDetail.objects.create(**detail)
            except Exception as err:
                print(err)
def pullServerList():
    reqHeaders = {'Content-Type': 'application/json'}
    req = urllib2.Request(SERVER_LIST_ADDR, headers = reqHeaders)
    ## 返回值格式化
    result = json.loads(urllib2.urlopen(req).read())
    for i in result['data']:
        exists = Server.objects.filter(hware_id = i['idc_hardware_serial']).exists()
        if exists:
            server = Server.objects.get(hware_id = i['idc_hardware_serial'])
            server.ips = i['idc_physical_os_ips']
            server.bussiness = i['idc_business']
            server.project = i['idc_project']
            server.update_date = timezone.now()
            try:
                server.save()
            except Exception as err:
                print(err)
        else:
            server = {
                'hware_id': i['idc_hardware_serial'],
                'ips': i['idc_physical_os_ips'],
                'bussiness': i['idc_business'],
                'project': i['idc_project'],
            }
            try:
                Server.objects.create(**server)
            except Exception as err:
                print(err)

def procDetect():
    params = {
        'client': 'local',
        'fun': 'proc.detect',
        'tgt': '*'
    }
    result = salt.postRequest(params)
    result = result['return'][0]
    for k in result.keys():
        exists = Minion.objects.filter(key = k).exists()
        if not exists:
            print('minion节点暂未记录, 请稍等...')
            continue

        minion = Minion.objects.get(key = k)        
        procs = ProcRunning.objects.filter(minion = minion).delete()
        ## 未返回数据的清空后就跳过
        if result[k] == False:
            continue
        for proc in result[k]:
            start_date = timezone.datetime.fromtimestamp(proc['start_date'])
            start_date = timezone.make_aware(start_date)
            procRunning = {
                'minion': minion,
                'pid': proc['pid'],
                'port': 0 if proc['port'] == None else proc['port'],
                'ps_str': proc['ps_str'],
                'user': proc['user'],
                'key': proc['key'],
                'start_date': start_date
            }
            try:
                ProcRunning.objects.create(**procRunning)
            except Exception, e:
                print(e)
